/** ***********************************************************************************
* @file         mcu_data_format.c
* @brief        定义MCU数据传输协议的结构体描述
* @details      主要是用来定义MCU数据传输格式，以及数据接口
* @author       杨小珛
* @date         2021/01/30
* @copyright    北京高知科技有限公司    
* @version      V1.0
* @attention    无
**************************************************************************************/
#ifndef MCU_DATA_FORMAT_H
#define MCU_DATA_FORMAT_H

#include "os_app.h"
#include "can_par_list.h"

#define MCU_PROTOCOL_HEAD                0x7E            ///< 协议数据头标识
#define MCU_PROTOCOL_TAIL                0x7E            ///< 协议数据尾标识

#define MCU_ESC_CODE                     0x7D            ///< 协议数据转义码,根据其后跟的数值确定是否为转义
#define MCU_ESC_CHAR1                    0x02            ///< 协议数据转义字符1
#define MCU_ESC_CHAR2                    0x01            ///< 协议数据转义字符2
#define MCU_ESC_FLAG1                    0x7E            ///< 协议数据转义值1,用0x7D + 0x02转义
#define MCU_ESC_FLAG2                    0x7D            ///< 协议数据转义值2,用0x7D + 0x01转义

#define MCU_HEAD_SIZE                    12              ///< 协议数据头大小

#define MCU_PK_SIZE                      1510            ///< 协议数据包大小
#define MCU_DATA_SIZE                    1500            ///< 协议数据大小
#define MCU_VHE_ID_SIZE                  6               ///< 车辆ID数据长度

/*********************PROTOCOL COMMAND CODE DEFINE***************************/
/*****CPU发送命令字*******/
#define CPU_COMMON_RSP                  0x1000          //CPU通用应答  
#define CPU_HEART                       0x1005          //CPU心跳 
#define CPU_IO_STATE                    0x1011          //CPU心跳 
#define CPU_POWER_RESET                 0x1012          //重启CPU电源  ，使用通用应答
#define CPU_VER_QUERY                   0x1013          //查询CPU版本
#define CPU_DOWN_UPGRADE                0x1015          //CPU下发终端升级包，使用通用应答
#define CPU_VEHICLE_ST                  0x1017          //CPU查询车辆状态
#define CPU_WRITE_UTC                   0x1018          //写UTC时间 ，使用通用应答
#define CPU_READ_UTC                    0x1019          //读UTC时间
#define CPU_WRITE_PARA                  0x101A          //CPU写参数表
#define CPU_READ_PARA                   0x101B          //CPU读参数表
#define CPU_WRITE_FLASH                 0x101C          //写FLASH数据，使用通用应答
#define CPU_READ_FLASH                  0x101D          //读FLASH数据
#define CPU_ERASE_FLASH                 0x101E          //擦除FLASH数据，使用通用应答
#define CPU_RESET_MCU                   0x1020          //CPU重启MCU，使用通用应答
#define CPU_CLEAR_MCU_DATA              0x1021          //CPU清楚MCU数据，使用通用应答
#define CPU_FIND_CAR                    0x1030          //CPU寻车命令，使用通用应答
#define CPU_CAR_LOCK                    0x1031          //CPU车锁命令，使用通用应答
#define CPU_POWER_OFF                   0x1032          //CPU断电命令，使用通用应答
#define CPU_CAN_CONTROL                 0x1033          //CPU CAN模块控制命令，使用通用应答
#define CPU_WRITE_CA                    0x1035          //CPU 写CA证书，使用通用应答
#define CPU_READ_CA                     0x1036          //CPU 读CA证书
#define CPU_VERSION_RSQ                 0x1038          //CPU 版本号请求下发
#define CPU_TIME_RSQ                    0x1039          //CPU 时间请求下发
#define CPU_INFORM_IAP                  0x1050          //CPU通知IAP进行升级，使用通用应答
#define CPU_UPGRADE_RSQ                 0x1051          //CPU下发升级包
#define CPU_SEND_KEY                    0x1060          //CPU发送钥匙板透传协议
#define CPU_SPI_INIT                    0x101F          //CPU发送初始化SPI，使用通用应答
#define CPU_SIM_CARD                    0x1061          //CPU发送SIM卡贴换，使用通用应答
#define CPU_CFG_PORT                    0x1070          //CPU配置GPIO，使用通用应答
#define CPU_WR_PORT                     0x1071          //CPU读写GPIO
#define CPU_CAN_INIT                    0x1072          //CPU初始化CAN驱动，使用通用应答
#define CPU_CFG_CAN_ID                  0x1073          //CPU配置CAN ID信息，使用通用应答
#define CPU_SEND_CAN_DATA               0x1074          //CPU主动发送CAN数据，使用通用应答
#define CPU_CAN_CLOSE                   0x1076          //CPU关闭CAN驱动，使用通用应答
#define CPU_UART_OPEN                   0x1077          //CPU打开UART驱动，使用通用应答
#define CPU_SEND_UART_DATA              0x1078          //CPU发送UART数据
#define CPU_UART_CLOSE                  0x1079          //CPU关闭UART驱动，使用通用应答
#define CPU_RUN_STATE                   0x107A          //CPU控制MCU运行状态，使用通用应答


/*****MCU发送命令字*******/
#define MCU_COMMON_RSP                  0x2000          //MCU通用应答 
#define MCU_HEART_RSQ                   0x2005          //MCU心跳 应答
#define MCU_IO_STATE                    0x2011          //MCU IO状态应答，使用通用应答
#define MCU_VER_QUERY_RSQ               0x2013          //查询CPU版本应答
#define MCU_UPGRADE_RES                 0x2016          //MCU发送终端设计结果
#define MCU_VEHICLE_ST_RSQ              0x2017          //MCU上报车辆状态
#define MCU_READ_UTC_RSQ                0x2019          //应答UTC时间
#define MCU_READ_PARA_RSQ               0x201B          //应答参数表命令 
#define MCU_READ_FLASH_RSQ              0x201D          //应答读FLASH数据
#define MCU_INFORM_MCU                  0x2022          //MCU通知CPU，使用通用应答
#define MCU_READ_CA_RSQ                 0x2036          //MCU应答CA证书
#define MCU_CA_PC                       0x2037          //MCU应答CA证书给PC，使用通用应答
#define MCU_RSQ_VERSION                 0x2038          //MCU应答CA证书，发送给PC
#define MCU_RSQ_TIME                    0x2039          //MCU请求CPU时间
#define MCU_RSQ_UPGRADE                 0x2051          //MCU请求CPU发送升级包
#define MCU_REQ_UPGRADE_RES             0x2052          //MCU应答升级结果，使用通用应答
#define MCU_SEND_KEY_REQ                0x2060          //MCU应答钥匙板透传协议
#define MCU_WR_INT_PORT_REQ             0x2071          //MCU读写GPIO应答，MCU GPIO中断请求，使用通用应答
//#define MCU_INT_PORT                    0x2071          //MCU GPIO中断请求，使用通用应答
#define MCU_SEND_CAN_DATA               0x2074          //MCU主动发送CAN数据，使用通用应答
#define MCU_SEND_CAN_ST                 0x2075          //MCU主动发送CAN硬件状态，使用通用应答
#define MCU_SEND_UART_DATA_REQ          0x2078          //MCU应答CPU UART数据
#define MCU_DRIVE_INIT_REQ              0x207B          //MCU主动发送驱动初始化请求，使用通用应答

/*****PC发送命令字*******/
#define CPU_WRITE_PC                    0x3010          //PC写参数表预留，使用通用应答
#define CPU_READ_PC                     0x3011          //PC读参数表预留，使用通用应答
#define PC_SEND_MCU                     0x3001          //PC透传到L610数据。
#define CPU_SEND_PC                     0x2020          //CPU透传到PC数据。
#define PC_WRITE_CA                     0x3012          //PC写CA证书预留。

/****************************************************************************************
*协议消息结构(Message data structure)
******************************************************************************************/

typedef  struct
{
    uint16_t    id;                             ///< 消息ID
    union                                       ///< 消息属性
    {
        uint16_t    attr;
        struct
        {
            uint16_t    alen    : 10;           ///< 消息体长度
            uint16_t    acrypt  : 3;            ///< 加密方式
            uint16_t    pk_flag : 1;            ///< 分包标志
            uint16_t    arsv    : 2;            ///< 保留
        };
    };                                          ///< 消息体属性
    uint8_t     veh_id[MCU_VHE_ID_SIZE];        ///< 终端车辆ID
    uint16_t    sn;                             ///< 消息流水号
    union                                       ///< 消息包封装项
    {
        uint8_t     data[MCU_PK_SIZE];           ///< 消息数据
        struct                                  ///< 消息包封装项
        {
            uint16_t    pk_total;               ///< 消息总包数
            uint16_t    pk_idx;                 ///< 消息包序号
            uint8_t     pk_data[MCU_DATA_SIZE];  ///< 消息数据
        };
    };
}mcu_protocol_msg_t;

#define MCU_PROTOCOL_MSG_MAX_LEN    ( sizeof(mcu_protocol_msg_t) )

/****************************************************************************************
* CPU与MCU 通信数据格式结构体
******************************************************************************************/
#pragma pack(1)

typedef  struct
{
    uint16_t sn;            /*对应的终端消息的流水号*/
    uint16_t id;            /*对应的终端消息的ID*/
    uint8_t res;            /*0：成功/确认；1：失败；2：消息有误*/
}mcu_general_response_t;/*通用应答结构体*/

typedef  struct
{
    uint8_t channel;        /*CAN通道数，目前MCU只保留两路CAN1/CAN2通道。有效值为1,2；*/
    uint32_t cid;           /*CAN ID信息，需要发送ID信息；*/
    uint8_t len;            /*CAN 发送数据的长度*/
    uint8_t data[8];        /*CAN 发送数据信息*/
}mcu_can_send_infor_t;/*CAN 发送数据结构体*/

#define MCU_CAN_ID_NUM    100  //CAN ID 数量

typedef  struct
{
    uint8_t channel;        /*CAN通道数，目前MCU只保留两路CAN1/CAN2通道。有效值为1,2；*/
    uint8_t num;            /*CAN ID数量，有效值0~100；（预期值后期可做更改）*/
    uint32_t cid[MCU_CAN_ID_NUM]; /*CAN ID，MCU需要过滤的CAN ID列表信息。*/
}mcu_can_id_infor_t;/*CAN 发送数据结构体*/


#define MCU_CAN_DATA_LEN    8  //CAN 数据长度
#define MCU_CAN_FORMAT_LEN    100

typedef  struct
{
    uint8_t channel;        /*CAN通道数，目前MCU只保留两路CAN1/CAN2通道。有效值为1,2；*/
    uint32_t cid;           /*CAN ID，MCU需要过滤的CAN ID列表信息。*/
    uint8_t len;
    uint8_t data[MCU_CAN_DATA_LEN];
}mcu_can_data_infor_t;/*CAN 发送数据结构体*/

typedef  struct
{
    uint8_t num;            /*CAN 帧数量，有效值1~100；（预期值后期可做更改）*/
    mcu_can_data_infor_t infor[MCU_CAN_FORMAT_LEN];
}mcu_can_data_format_t;/*CAN 发送数据结构体*/


typedef struct
{
    union                                   
    {
        volatile uint16_t        port;          // PORT端口
        struct
        {
            volatile uint16_t    pin   :  8;    //端口号，有效值：0-15，BCD码
            volatile uint16_t    name  :  4;    //端口名称，0xA、0xB、0xC、0xD、0xE、0xF
            volatile uint16_t    st    :  2;    //状态位模式，0：OUTPUT，1：INPUT，2：ADC ，3：INTERRRUPT (配置模式)
            volatile uint16_t    mode  :  2;    
            /*配置模式，
            0：GPIO_MODE_IPD （输入配置，下拉）
               GPIO_MODE_OUT_OD （输出配置，开漏）
               EXTI_TRIG_RISING  （中断配置，上升沿）
              （配置输出时，初始化状态为高电平）
            1：GPIO_MODE_IPU （输入配置，上拉）
               GPIO_MODE_OUT_PP（输出配置，推完）
               EXTI_TRIG_FALLING（中断配置，下降沿）
              （配置输出时，初始化状态为高电平）
            2：EXTI_TRIG_BOTH （中断配置，上升、下降）
               GPIO_MODE_OUT_OD （输出配置，开漏）
              （配置输出时，初始化状态为低电平）
            3：GPIO_MODE_OUT_PP（输出配置，推完）
              （配置输出时，初始化状态为低电平）*/
            //读写模式，0：低电平，1：高电平 （状态位为输出模式时，此状态有效）
        };
    };
} mcu_port_cfg_infor_t;

typedef struct
{
    union                                   
    {
        volatile uint16_t        port;          // PORT端口
        struct
        {
            volatile uint16_t    pin   :  8;    //端口号，有效值：0-15，BCD码
            volatile uint16_t    name  :  4;    //端口名称，0xA、0xB、0xC、0xD、0xE、0xF
            volatile uint16_t    st    :  4;    //状态位模式，0：OUTPUT，1：INPUT，2：ADC
        };
    };
    volatile uint16_t            data;          //IO数据：
    //状态位1时：0：低电平信号，1：高电平信号。
    //状态位2时：ADC数据值，基准电压与转换方式以电路设计为准。
    //其他状态时无效。
} mcu_port_wr_int_ack_infor_t;


#pragma pack()

/****************************************************************************************
MCU接收消息数据结构
*****************************************************************************************/
typedef struct
{
    uint8_t     *data;           // 数据指针
    uint32_t    type;            // 消息类型
    uint32_t    valid;           // 消息有效标识
    uint32_t    attr;            // 数据属性
} mcu_protocol_infor_t;

#define MCU_PROTOCOL_QUEUE_MAX_NUM         ( 5 )
#define MCU_PROTOCOL_QUEUE_WAIT_TIME       ( 3000 )
#define MCU_PROTOCOL_QUEUE_SEND_TIME       ( 100 )

typedef enum
{   
    /*****************SPI FLASH********************/
    CPU_SPI_INIT_QUEUE_ID = 0, 
    CPU_ERASE_FLASH_QUEUE_ID,  
    CPU_READ_FLASH_QUEUE_ID,
    CPU_WRITE_FLASH_QUEUE_ID,
    /*****************PORT DEV********************/   
    CPU_CFG_PORT_QUEUE_ID,
    CPU_WR_PORT_QUEUE_ID,
    /*****************CAN DEV*********************/   
    CPU_CAN_INIT_QUEUE_ID,
    CPU_CFG_CAN_ID_QUEUE_ID,
    CPU_SEND_CAN_DATA_QUEUE_ID,
    CPU_CAN_CLOSE_QUEUE_ID,
    /*****************UART DEV********************/   
    CPU_UART_OPEN_QUEUE_ID,
    CPU_UART_CLOSE_QUEUE_ID,
    /*****************RUN ST**********************/   
    CPU_RUN_STATE_QUEUE_ID,
    /*****************MCU PORT ST*****************/   
    MCU_WR_INT_PORT_QUEUE_ID,
    /*****************VER QUERY*******************/   
    CPU_VER_QUERY_QUEUE_ID,

    MCU_PROTOCOL_RECV_NUM,            /*消息队列总数*/
}mcu_protocol_recv_queue_e;


/****************************************************************************************
MCU 初始化驱动状态
*****************************************************************************************/
typedef enum
{   
    CAN_INIT_DEV = 0x01,
    RS232_INIT_DEV,
    PORT_INIT_DEV,
}mcu_protocol_dev_status_e;
/****************************************************************************************
CPU 接收MCU主动发送的数据类型
*****************************************************************************************/
typedef enum
{   
    CAN_RECV_DATA = 0x01,
    RS232_RECV_DATA,
    DEVICE_RECV_INIT,
    CAN_NM_RELAR_CTRL,
    RF_KEY_DATA_RECV,
}mcu_protocol_can_recv_status_e;

/****************************************************************************************
MCU控制运行的状态
*****************************************************************************************/
typedef enum
{   
    CONTROL_ST_INIT = 0x00,
    CONTROL_RUN_MCU_ST = 0x01,
    CONTROL_SLEEP_MCU_ST,
    CONTROL_STOP_MCU_ST,
    CONTROL_RESTART_MCU_ST,
    CONTROL_RESTART_CPU_ST,
    CONTROL_ONLY_RESTART_CPU_ST = 0x0A,
}mcu_protocol_control_status_e;

/** ****************************************************************************
* @remarks       uint32_t mcu_protocol_flash_open( void )
* @brief         打开MCU 底层数据操作,专门操作FLASH 的接口
* @param[in]     无
* @param[out]    无
* @return        pdPASS 打开成功，pdFAIL打开失败
* @attention     无
*******************************************************************************/
extern uint32_t mcu_protocol_flash_open( void );

/** ****************************************************************************
* @remarks       uint32_t mcu_protocol_commad_parse( uint8_t *pdata, uint32_t size )
* @brief         命令处理
* @param[in]     *pdata:   数据指针
* @param[in]     size:       数据大小
* @param[out]    无
* @return        pdPASS成功/pdFAIL失败
* @attention     无
*******************************************************************************/
extern uint32_t mcu_protocol_commad_parse( uint8_t *pdata, uint32_t size );

/** ****************************************************************************
* @remarks       uint32_t mcu_protocol_pack_send( mcu_protocol_msg_t *pmsg  )
* @brief         协议处理：数据打包发送
* @param[in]     pMsg:   消息结构指针
* @param[out]    无
* @return        pdPASS成功/pdFAIL失败
* @attention     无
*******************************************************************************/
extern uint32_t mcu_protocol_pack_send( mcu_protocol_msg_t *pmsg );

/** ****************************************************************************
* @remarks       uint32_t mcu_protocol_general_response_send(uint16_t sn, uint16_t id,  uint8_t res )
* @brief         通用应答发送
* @param[in]     sn 流水号 ，id 发送ID ，res结果
* @param[out]    无
* @return        pdPASS成功/pdFAIL失败
* @attention     无
*******************************************************************************/
extern uint32_t mcu_protocol_general_response_send( uint16_t sn, uint16_t id,  uint8_t res );

/** ****************************************************************************
* @remarks       uint32_t mcu_protocol_heartbear_response_send( void )
* @brief         CPU 心跳应答
* @param[in]     *data 数据源地址， len 数据长度
* @param[out]    无
* @return        pdPASS成功/pdFAIL失败
* @attention     无
*******************************************************************************/
extern uint32_t mcu_protocol_heartbear_response_send( uint8_t *data, uint16_t len );

/** ****************************************************************************
* @remarks       uint32_t mcu_protocol_dev_init( void )
* @brief         MCU 底层驱动初始化
* @param[in]     dev_st 驱动初始化类型
* @param[out]    无
* @return        pdPASS成功/pdFAIL失败
* @attention     无
*******************************************************************************/
extern uint32_t mcu_protocol_dev_init( mcu_protocol_dev_status_e dev_st );

/** ****************************************************************************
* @remarks       uint32_t mcu_protocol_can_dev_init( void )
* @brief         MCU CAN底层驱动初始化
* @param[in]     无
* @param[out]    无
* @return        pdPASS成功/pdFAIL失败
* @attention     无
*******************************************************************************/
extern uint32_t mcu_protocol_can_dev_init( void );

/** ****************************************************************************
* @remarks       uint32_t mcu_protocol_rs232_dev_init( void )
* @brief         MCU RS232底层驱动初始化
* @param[in]     无
* @param[out]    无
* @return        pdPASS成功/pdFAIL失败
* @attention     无
*******************************************************************************/
extern uint32_t mcu_protocol_rs232_dev_init( void );

/** ****************************************************************************
* @remarks       uint32_t mcu_protocol_port_dev_init( void )
* @brief         MCU PORT底层驱动初始化
* @param[in]     无
* @param[out]    无
* @return        pdPASS成功/pdFAIL失败
* @attention     无
*******************************************************************************/
extern uint32_t mcu_protocol_port_dev_init( void );

/** ****************************************************************************
* @remarks       uint32_t mcu_protocol_can_id_filtering_init( void )
* @brief         MCU CAN ID 过滤设置
* @param[in]     无
* @param[out]    无
* @return        pdPASS成功/pdFAIL失败
* @attention     无
*******************************************************************************/
extern uint32_t mcu_protocol_can_id_filtering_init( void );

/** ****************************************************************************
* @remarks       uint32_t mcu_protocol_can_id_init( uint8_t channel )
* @brief         MCU CAN ID 过滤设置
* @param[in]     channel CAN 通道 1,2
* @param[out]    无
* @return        pdPASS成功/pdFAIL失败
* @attention     无
*******************************************************************************/
extern uint32_t mcu_protocol_can_id_init( uint8_t channel );

/** ****************************************************************************
* @remarks       uint32_t mcu_protocol_can_data_send( can_send_infor_t *infor , uint8_t *exit)
* @brief         MCU 协议组包 发送CAN 数据
* @param[in]     *infor CAN 发送信息，*exit 强制退出状态
* @param[out]    无
* @return        pdPASS成功/pdFAIL失败
* @attention     无
*******************************************************************************/
extern uint32_t mcu_protocol_can_data_send( can_send_infor_t *infor, uint8_t *exit);

/** ****************************************************************************
* @remarks       uint32_t mcu_protocol_can_format_recv( uint8_t *data , uint16_t len )
* @brief         MCU CAN 数据包 格式数据接收处理
* @param[in]     *data 数据源地址，len数据长度
* @param[out]    无
* @return        pdPASS成功/pdFAIL失败
* @attention     无
*******************************************************************************/
extern uint32_t mcu_protocol_can_format_recv( uint8_t *data , uint16_t len );

/** ****************************************************************************
* @remarks       uint32_t mcu_protocol_port_signal_read( port_input_infor_t *infor , uint16_t *out )
* @brief         读取MCU PORT 数据
* @param[in]     *infor PORT配置信息
* @param[out]    *out 数据输出目标地址
* @return        pdPASS成功/pdFAIL失败
* @attention     无
*******************************************************************************/
extern uint32_t mcu_protocol_port_signal_read( port_input_infor_t *infor , uint16_t *out );

/** ****************************************************************************
* @remarks       uint32_t mcu_protocol_port_signal_write( port_output_infor_t *infor , uint8_t *exit)
* @brief         控制PORT 操作
* @param[in]     *infor PORT 发送信息，*exit强制退出状态
* @param[out]    无
* @return        pdPASS成功/pdFAIL失败
* @attention     无
*******************************************************************************/
extern uint32_t mcu_protocol_port_signal_write( port_output_infor_t *infor , uint8_t *exit);


/** ****************************************************************************
* @remarks       uint32_t mcu_protocol_control_run_status( mcu_protocol_control_status_e status )
* @brief         控制MCU 运行的状态
* @param[in]     status  设置运行的状态
* @param[out]    无
* @return        pdPASS成功/pdFAIL失败
* @attention     无
*******************************************************************************/
extern uint32_t mcu_protocol_control_run_status( mcu_protocol_control_status_e status );

/** ****************************************************************************
* @remarks       uint32_t mcu_protocol_mcu_version_get( uint8_t *version, uint32_t *len )
* @brief         获取MCU系统版本号
* @param[in]     无
* @param[out]    *version 版本号目标地址， *len 版本号长度
* @return        pdPASS成功/pdFAIL失败
* @attention     无
*******************************************************************************/
extern uint32_t mcu_protocol_mcu_version_get( uint8_t *version, uint32_t *len );

/** ****************************************************************************
* @remarks       uint32_t mcu_protocol_mcu_port_cfg( mcu_port_cfg_infor_t  port_cfg )
* @brief         初始化MCU PORT
* @param[in]     port_cfg 引脚配置
* @param[out]    无
* @return        pdPASS成功/pdFAIL失败
* @attention     无
*******************************************************************************/
extern uint32_t mcu_protocol_mcu_port_cfg( mcu_port_cfg_infor_t  port_cfg );

/** ****************************************************************************
* @remarks       uint32_t mcu_protocol_mcu_port_read_write( port_input_infor_t *infor , uint16_t *out )
* @brief         读写MCU PORT 数据
* @param[in]     *infor PORT配置信息
* @param[out]    *out 数据输出目标地址
* @return        pdPASS成功/pdFAIL失败
* @attention     无
*******************************************************************************/
extern uint32_t mcu_protocol_mcu_port_read_write( mcu_port_cfg_infor_t  port_cfg , uint16_t *out );

#endif

